﻿// lib/handlebars/base.js
var Handlebars={};

Handlebars.VERSION="1.0.beta.6";

Handlebars.helpers={};
Handlebars.partials={};

Handlebars.registerHelper=function (name, fn, inverse) {
    if(inverse) { fn.not=inverse; }
    this.helpers[name]=fn;
};

Handlebars.registerPartial=function (name, str) {
    this.partials[name]=str;
};

Handlebars.registerHelper('helperMissing', function (arg) {
    if(arguments.length===2) {
        return undefined;
    } else {
        throw new Error("Could not find property '"+arg+"'");
    }
});

var toString=Object.prototype.toString, functionType="[object Function]";

Handlebars.registerHelper('blockHelperMissing', function (context, options) {
    var inverse=options.inverse||function () { }, fn=options.fn;


    var ret="";
    var type=toString.call(context);

    if(type===functionType) { context=context.call(this); }

    if(context===true) {
        return fn(this);
    } else if(context===false||context==null) {
        return inverse(this);
    } else if(type==="[object Array]") {
        if(context.length>0) {
            for(var i=0, j=context.length; i<j; i++) {
                ret=ret+fn(context[i]);
            }
        } else {
            ret=inverse(this);
        }
        return ret;
    } else {
        return fn(context);
    }
});

Handlebars.registerHelper('each', function (context, options) {
    var fn=options.fn, inverse=options.inverse;
    var ret="";

    if(context&&context.length>0) {
        for(var i=0, j=context.length; i<j; i++) {
            ret=ret+fn(context[i]);
        }
    } else {
        ret=inverse(this);
    }
    return ret;
});

Handlebars.registerHelper('if', function (context, options) {
    var type=toString.call(context);
    if(type===functionType) { context=context.call(this); }

    if(!context||Handlebars.Utils.isEmpty(context)) {
        return options.inverse(this);
    } else {
        return options.fn(this);
    }
});

Handlebars.registerHelper('unless', function (context, options) {
    var fn=options.fn, inverse=options.inverse;
    options.fn=inverse;
    options.inverse=fn;

    return Handlebars.helpers['if'].call(this, context, options);
});

Handlebars.registerHelper('with', function (context, options) {
    return options.fn(context);
});

Handlebars.registerHelper('log', function (context) {
    Handlebars.log(context);
});
;
// lib/handlebars/compiler/parser.js
/* Jison generated parser */
var handlebars=(function () {

    var parser={ trace: function trace() { },
        yy: {},
        symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "statements": 6, "simpleInverse": 7, "statement": 8, "openInverse": 9, "closeBlock": 10, "openBlock": 11, "mustache": 12, "partial": 13, "CONTENT": 14, "COMMENT": 15, "OPEN_BLOCK": 16, "inMustache": 17, "CLOSE": 18, "OPEN_INVERSE": 19, "OPEN_ENDBLOCK": 20, "path": 21, "OPEN": 22, "OPEN_UNESCAPED": 23, "OPEN_PARTIAL": 24, "params": 25, "hash": 26, "param": 27, "STRING": 28, "INTEGER": 29, "BOOLEAN": 30, "hashSegments": 31, "hashSegment": 32, "ID": 33, "EQUALS": 34, "pathSegments": 35, "SEP": 36, "$accept": 0, "$end": 1 },
        terminals_: { 2: "error", 5: "EOF", 14: "CONTENT", 15: "COMMENT", 16: "OPEN_BLOCK", 18: "CLOSE", 19: "OPEN_INVERSE", 20: "OPEN_ENDBLOCK", 22: "OPEN", 23: "OPEN_UNESCAPED", 24: "OPEN_PARTIAL", 28: "STRING", 29: "INTEGER", 30: "BOOLEAN", 33: "ID", 34: "EQUALS", 36: "SEP" },
        productions_: [0, [3, 2], [4, 3], [4, 1], [4, 0], [6, 1], [6, 2], [8, 3], [8, 3], [8, 1], [8, 1], [8, 1], [8, 1], [11, 3], [9, 3], [10, 3], [12, 3], [12, 3], [13, 3], [13, 4], [7, 2], [17, 3], [17, 2], [17, 2], [17, 1], [25, 2], [25, 1], [27, 1], [27, 1], [27, 1], [27, 1], [26, 1], [31, 2], [31, 1], [32, 3], [32, 3], [32, 3], [32, 3], [21, 1], [35, 3], [35, 1]],
        performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {

            var $0=$$.length-1;
            switch(yystate) {
                case 1: return $$[$0-1]
                    break;
                case 2: this.$=new yy.ProgramNode($$[$0-2], $$[$0])
                    break;
                case 3: this.$=new yy.ProgramNode($$[$0])
                    break;
                case 4: this.$=new yy.ProgramNode([])
                    break;
                case 5: this.$=[$$[$0]]
                    break;
                case 6: $$[$0-1].push($$[$0]); this.$=$$[$0-1]
                    break;
                case 7: this.$=new yy.InverseNode($$[$0-2], $$[$0-1], $$[$0])
                    break;
                case 8: this.$=new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0])
                    break;
                case 9: this.$=$$[$0]
                    break;
                case 10: this.$=$$[$0]
                    break;
                case 11: this.$=new yy.ContentNode($$[$0])
                    break;
                case 12: this.$=new yy.CommentNode($$[$0])
                    break;
                case 13: this.$=new yy.MustacheNode($$[$0-1][0], $$[$0-1][1])
                    break;
                case 14: this.$=new yy.MustacheNode($$[$0-1][0], $$[$0-1][1])
                    break;
                case 15: this.$=$$[$0-1]
                    break;
                case 16: this.$=new yy.MustacheNode($$[$0-1][0], $$[$0-1][1])
                    break;
                case 17: this.$=new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true)
                    break;
                case 18: this.$=new yy.PartialNode($$[$0-1])
                    break;
                case 19: this.$=new yy.PartialNode($$[$0-2], $$[$0-1])
                    break;
                case 20:
                    break;
                case 21: this.$=[[$$[$0-2]].concat($$[$0-1]), $$[$0]]
                    break;
                case 22: this.$=[[$$[$0-1]].concat($$[$0]), null]
                    break;
                case 23: this.$=[[$$[$0-1]], $$[$0]]
                    break;
                case 24: this.$=[[$$[$0]], null]
                    break;
                case 25: $$[$0-1].push($$[$0]); this.$=$$[$0-1];
                    break;
                case 26: this.$=[$$[$0]]
                    break;
                case 27: this.$=$$[$0]
                    break;
                case 28: this.$=new yy.StringNode($$[$0])
                    break;
                case 29: this.$=new yy.IntegerNode($$[$0])
                    break;
                case 30: this.$=new yy.BooleanNode($$[$0])
                    break;
                case 31: this.$=new yy.HashNode($$[$0])
                    break;
                case 32: $$[$0-1].push($$[$0]); this.$=$$[$0-1]
                    break;
                case 33: this.$=[$$[$0]]
                    break;
                case 34: this.$=[$$[$0-2], $$[$0]]
                    break;
                case 35: this.$=[$$[$0-2], new yy.StringNode($$[$0])]
                    break;
                case 36: this.$=[$$[$0-2], new yy.IntegerNode($$[$0])]
                    break;
                case 37: this.$=[$$[$0-2], new yy.BooleanNode($$[$0])]
                    break;
                case 38: this.$=new yy.IdNode($$[$0])
                    break;
                case 39: $$[$0-2].push($$[$0]); this.$=$$[$0-2];
                    break;
                case 40: this.$=[$$[$0]]
                    break;
            }
        },
        table: [{ 3: 1, 4: 2, 5: [2, 4], 6: 3, 8: 4, 9: 5, 11: 6, 12: 7, 13: 8, 14: [1, 9], 15: [1, 10], 16: [1, 12], 19: [1, 11], 22: [1, 13], 23: [1, 14], 24: [1, 15] }, { 1: [3] }, { 5: [1, 16] }, { 5: [2, 3], 7: 17, 8: 18, 9: 5, 11: 6, 12: 7, 13: 8, 14: [1, 9], 15: [1, 10], 16: [1, 12], 19: [1, 19], 20: [2, 3], 22: [1, 13], 23: [1, 14], 24: [1, 15] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 16: [2, 5], 19: [2, 5], 20: [2, 5], 22: [2, 5], 23: [2, 5], 24: [2, 5] }, { 4: 20, 6: 3, 8: 4, 9: 5, 11: 6, 12: 7, 13: 8, 14: [1, 9], 15: [1, 10], 16: [1, 12], 19: [1, 11], 20: [2, 4], 22: [1, 13], 23: [1, 14], 24: [1, 15] }, { 4: 21, 6: 3, 8: 4, 9: 5, 11: 6, 12: 7, 13: 8, 14: [1, 9], 15: [1, 10], 16: [1, 12], 19: [1, 11], 20: [2, 4], 22: [1, 13], 23: [1, 14], 24: [1, 15] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 16: [2, 9], 19: [2, 9], 20: [2, 9], 22: [2, 9], 23: [2, 9], 24: [2, 9] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 16: [2, 10], 19: [2, 10], 20: [2, 10], 22: [2, 10], 23: [2, 10], 24: [2, 10] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 16: [2, 11], 19: [2, 11], 20: [2, 11], 22: [2, 11], 23: [2, 11], 24: [2, 11] }, { 5: [2, 12], 14: [2, 12], 15: [2, 12], 16: [2, 12], 19: [2, 12], 20: [2, 12], 22: [2, 12], 23: [2, 12], 24: [2, 12] }, { 17: 22, 21: 23, 33: [1, 25], 35: 24 }, { 17: 26, 21: 23, 33: [1, 25], 35: 24 }, { 17: 27, 21: 23, 33: [1, 25], 35: 24 }, { 17: 28, 21: 23, 33: [1, 25], 35: 24 }, { 21: 29, 33: [1, 25], 35: 24 }, { 1: [2, 1] }, { 6: 30, 8: 4, 9: 5, 11: 6, 12: 7, 13: 8, 14: [1, 9], 15: [1, 10], 16: [1, 12], 19: [1, 11], 22: [1, 13], 23: [1, 14], 24: [1, 15] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 16: [2, 6], 19: [2, 6], 20: [2, 6], 22: [2, 6], 23: [2, 6], 24: [2, 6] }, { 17: 22, 18: [1, 31], 21: 23, 33: [1, 25], 35: 24 }, { 10: 32, 20: [1, 33] }, { 10: 34, 20: [1, 33] }, { 18: [1, 35] }, { 18: [2, 24], 21: 40, 25: 36, 26: 37, 27: 38, 28: [1, 41], 29: [1, 42], 30: [1, 43], 31: 39, 32: 44, 33: [1, 45], 35: 24 }, { 18: [2, 38], 28: [2, 38], 29: [2, 38], 30: [2, 38], 33: [2, 38], 36: [1, 46] }, { 18: [2, 40], 28: [2, 40], 29: [2, 40], 30: [2, 40], 33: [2, 40], 36: [2, 40] }, { 18: [1, 47] }, { 18: [1, 48] }, { 18: [1, 49] }, { 18: [1, 50], 21: 51, 33: [1, 25], 35: 24 }, { 5: [2, 2], 8: 18, 9: 5, 11: 6, 12: 7, 13: 8, 14: [1, 9], 15: [1, 10], 16: [1, 12], 19: [1, 11], 20: [2, 2], 22: [1, 13], 23: [1, 14], 24: [1, 15] }, { 14: [2, 20], 15: [2, 20], 16: [2, 20], 19: [2, 20], 22: [2, 20], 23: [2, 20], 24: [2, 20] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 16: [2, 7], 19: [2, 7], 20: [2, 7], 22: [2, 7], 23: [2, 7], 24: [2, 7] }, { 21: 52, 33: [1, 25], 35: 24 }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 16: [2, 8], 19: [2, 8], 20: [2, 8], 22: [2, 8], 23: [2, 8], 24: [2, 8] }, { 14: [2, 14], 15: [2, 14], 16: [2, 14], 19: [2, 14], 20: [2, 14], 22: [2, 14], 23: [2, 14], 24: [2, 14] }, { 18: [2, 22], 21: 40, 26: 53, 27: 54, 28: [1, 41], 29: [1, 42], 30: [1, 43], 31: 39, 32: 44, 33: [1, 45], 35: 24 }, { 18: [2, 23] }, { 18: [2, 26], 28: [2, 26], 29: [2, 26], 30: [2, 26], 33: [2, 26] }, { 18: [2, 31], 32: 55, 33: [1, 56] }, { 18: [2, 27], 28: [2, 27], 29: [2, 27], 30: [2, 27], 33: [2, 27] }, { 18: [2, 28], 28: [2, 28], 29: [2, 28], 30: [2, 28], 33: [2, 28] }, { 18: [2, 29], 28: [2, 29], 29: [2, 29], 30: [2, 29], 33: [2, 29] }, { 18: [2, 30], 28: [2, 30], 29: [2, 30], 30: [2, 30], 33: [2, 30] }, { 18: [2, 33], 33: [2, 33] }, { 18: [2, 40], 28: [2, 40], 29: [2, 40], 30: [2, 40], 33: [2, 40], 34: [1, 57], 36: [2, 40] }, { 33: [1, 58] }, { 14: [2, 13], 15: [2, 13], 16: [2, 13], 19: [2, 13], 20: [2, 13], 22: [2, 13], 23: [2, 13], 24: [2, 13] }, { 5: [2, 16], 14: [2, 16], 15: [2, 16], 16: [2, 16], 19: [2, 16], 20: [2, 16], 22: [2, 16], 23: [2, 16], 24: [2, 16] }, { 5: [2, 17], 14: [2, 17], 15: [2, 17], 16: [2, 17], 19: [2, 17], 20: [2, 17], 22: [2, 17], 23: [2, 17], 24: [2, 17] }, { 5: [2, 18], 14: [2, 18], 15: [2, 18], 16: [2, 18], 19: [2, 18], 20: [2, 18], 22: [2, 18], 23: [2, 18], 24: [2, 18] }, { 18: [1, 59] }, { 18: [1, 60] }, { 18: [2, 21] }, { 18: [2, 25], 28: [2, 25], 29: [2, 25], 30: [2, 25], 33: [2, 25] }, { 18: [2, 32], 33: [2, 32] }, { 34: [1, 57] }, { 21: 61, 28: [1, 62], 29: [1, 63], 30: [1, 64], 33: [1, 25], 35: 24 }, { 18: [2, 39], 28: [2, 39], 29: [2, 39], 30: [2, 39], 33: [2, 39], 36: [2, 39] }, { 5: [2, 19], 14: [2, 19], 15: [2, 19], 16: [2, 19], 19: [2, 19], 20: [2, 19], 22: [2, 19], 23: [2, 19], 24: [2, 19] }, { 5: [2, 15], 14: [2, 15], 15: [2, 15], 16: [2, 15], 19: [2, 15], 20: [2, 15], 22: [2, 15], 23: [2, 15], 24: [2, 15] }, { 18: [2, 34], 33: [2, 34] }, { 18: [2, 35], 33: [2, 35] }, { 18: [2, 36], 33: [2, 36] }, { 18: [2, 37], 33: [2, 37]}],
        defaultActions: { 16: [2, 1], 37: [2, 23], 53: [2, 21] },
        parseError: function parseError(str, hash) {
            throw new Error(str);
        },
        parse: function parse(input) {
            var self=this, stack=[0], vstack=[null], lstack=[], table=this.table, yytext="", yylineno=0, yyleng=0, recovering=0, TERROR=2, EOF=1;
            this.lexer.setInput(input);
            this.lexer.yy=this.yy;
            this.yy.lexer=this.lexer;
            if(typeof this.lexer.yylloc=="undefined")
                this.lexer.yylloc={};
            var yyloc=this.lexer.yylloc;
            lstack.push(yyloc);
            if(typeof this.yy.parseError==="function")
                this.parseError=this.yy.parseError;
            function popStack(n) {
                stack.length=stack.length-2*n;
                vstack.length=vstack.length-n;
                lstack.length=lstack.length-n;
            }
            function lex() {
                var token;
                token=self.lexer.lex()||1;
                if(typeof token!=="number") {
                    token=self.symbols_[token]||token;
                }
                return token;
            }
            var symbol, preErrorSymbol, state, action, a, r, yyval={}, p, len, newState, expected;
            while(true) {
                state=stack[stack.length-1];
                if(this.defaultActions[state]) {
                    action=this.defaultActions[state];
                } else {
                    if(symbol==null)
                        symbol=lex();
                    action=table[state]&&table[state][symbol];
                }
                if(typeof action==="undefined"||!action.length||!action[0]) {
                    if(!recovering) {
                        expected=[];
                        for(p in table[state])
                            if(this.terminals_[p]&&p>2) {
                                expected.push("'"+this.terminals_[p]+"'");
                            }
                        var errStr="";
                        if(this.lexer.showPosition) {
                            errStr="Parse error on line "+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(", ")+", got '"+this.terminals_[symbol]+"'";
                        } else {
                            errStr="Parse error on line "+(yylineno+1)+": Unexpected "+(symbol==1?"end of input":"'"+(this.terminals_[symbol]||symbol)+"'");
                        }
                        this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol]||symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected });
                    }
                }
                if(action[0] instanceof Array&&action.length>1) {
                    throw new Error("Parse Error: multiple actions possible at state: "+state+", token: "+symbol);
                }
                switch(action[0]) {
                    case 1:
                        stack.push(symbol);
                        vstack.push(this.lexer.yytext);
                        lstack.push(this.lexer.yylloc);
                        stack.push(action[1]);
                        symbol=null;
                        if(!preErrorSymbol) {
                            yyleng=this.lexer.yyleng;
                            yytext=this.lexer.yytext;
                            yylineno=this.lexer.yylineno;
                            yyloc=this.lexer.yylloc;
                            if(recovering>0)
                                recovering--;
                        } else {
                            symbol=preErrorSymbol;
                            preErrorSymbol=null;
                        }
                        break;
                    case 2:
                        len=this.productions_[action[1]][1];
                        yyval.$=vstack[vstack.length-len];
                        yyval._$={ first_line: lstack[lstack.length-(len||1)].first_line, last_line: lstack[lstack.length-1].last_line, first_column: lstack[lstack.length-(len||1)].first_column, last_column: lstack[lstack.length-1].last_column };
                        r=this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
                        if(typeof r!=="undefined") {
                            return r;
                        }
                        if(len) {
                            stack=stack.slice(0, -1*len*2);
                            vstack=vstack.slice(0, -1*len);
                            lstack=lstack.slice(0, -1*len);
                        }
                        stack.push(this.productions_[action[1]][0]);
                        vstack.push(yyval.$);
                        lstack.push(yyval._$);
                        newState=table[stack[stack.length-2]][stack[stack.length-1]];
                        stack.push(newState);
                        break;
                    case 3:
                        return true;
                }
            }
            return true;
        }
    }; /* Jison generated lexer */
    var lexer=(function () {

        var lexer=({ EOF: 1,
            parseError: function parseError(str, hash) {
                if(this.yy.parseError) {
                    this.yy.parseError(str, hash);
                } else {
                    throw new Error(str);
                }
            },
            setInput: function (input) {
                this._input=input;
                this._more=this._less=this.done=false;
                this.yylineno=this.yyleng=0;
                this.yytext=this.matched=this.match='';
                this.conditionStack=['INITIAL'];
                this.yylloc={ first_line: 1, first_column: 0, last_line: 1, last_column: 0 };
                return this;
            },
            input: function () {
                var ch=this._input[0];
                this.yytext+=ch;
                this.yyleng++;
                this.match+=ch;
                this.matched+=ch;
                var lines=ch.match(/\n/);
                if(lines) this.yylineno++;
                this._input=this._input.slice(1);
                return ch;
            },
            unput: function (ch) {
                this._input=ch+this._input;
                return this;
            },
            more: function () {
                this._more=true;
                return this;
            },
            pastInput: function () {
                var past=this.matched.substr(0, this.matched.length-this.match.length);
                return (past.length>20?'...':'')+past.substr(-20).replace(/\n/g, "");
            },
            upcomingInput: function () {
                var next=this.match;
                if(next.length<20) {
                    next+=this._input.substr(0, 20-next.length);
                }
                return (next.substr(0, 20)+(next.length>20?'...':'')).replace(/\n/g, "");
            },
            showPosition: function () {
                var pre=this.pastInput();
                var c=new Array(pre.length+1).join("-");
                return pre+this.upcomingInput()+"\n"+c+"^";
            },
            next: function () {
                if(this.done) {
                    return this.EOF;
                }
                if(!this._input) this.done=true;

                var token,
            match,
            col,
            lines;
                if(!this._more) {
                    this.yytext='';
                    this.match='';
                }
                var rules=this._currentRules();
                for(var i=0; i<rules.length; i++) {
                    match=this._input.match(this.rules[rules[i]]);
                    if(match) {
                        lines=match[0].match(/\n.*/g);
                        if(lines) this.yylineno+=lines.length;
                        this.yylloc={ first_line: this.yylloc.last_line,
                            last_line: this.yylineno+1,
                            first_column: this.yylloc.last_column,
                            last_column: lines?lines[lines.length-1].length-1:this.yylloc.last_column+match[0].length
                        }
                        this.yytext+=match[0];
                        this.match+=match[0];
                        this.matches=match;
                        this.yyleng=this.yytext.length;
                        this._more=false;
                        this._input=this._input.slice(match[0].length);
                        this.matched+=match[0];
                        token=this.performAction.call(this, this.yy, this, rules[i], this.conditionStack[this.conditionStack.length-1]);
                        if(token) return token;
                        else return;
                    }
                }
                if(this._input==="") {
                    return this.EOF;
                } else {
                    this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
                    { text: "", token: null, line: this.yylineno });
                }
            },
            lex: function lex() {
                var r=this.next();
                if(typeof r!=='undefined') {
                    return r;
                } else {
                    return this.lex();
                }
            },
            begin: function begin(condition) {
                this.conditionStack.push(condition);
            },
            popState: function popState() {
                return this.conditionStack.pop();
            },
            _currentRules: function _currentRules() {
                return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
            },
            topState: function () {
                return this.conditionStack[this.conditionStack.length-2];
            },
            pushState: function begin(condition) {
                this.begin(condition);
            } 
        });
        lexer.performAction=function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {

            var YYSTATE=YY_START
            switch($avoiding_name_collisions) {
                case 0:
                    if(yy_.yytext.slice(-1)!=="\\") this.begin("mu");
                    if(yy_.yytext.slice(-1)==="\\") yy_.yytext=yy_.yytext.substr(0, yy_.yyleng-1), this.begin("emu");
                    if(yy_.yytext) return 14;

                    break;
                case 1: return 14;
                    break;
                case 2: this.popState(); return 14;
                    break;
                case 3: return 24;
                    break;
                case 4: return 16;
                    break;
                case 5: return 20;
                    break;
                case 6: return 19;
                    break;
                case 7: return 19;
                    break;
                case 8: return 23;
                    break;
                case 9: return 23;
                    break;
                case 10: yy_.yytext=yy_.yytext.substr(3, yy_.yyleng-5); this.popState(); return 15;
                    break;
                case 11: return 22;
                    break;
                case 12: return 34;
                    break;
                case 13: return 33;
                    break;
                case 14: return 33;
                    break;
                case 15: return 36;
                    break;
                case 16: /*ignore whitespace*/
                    break;
                case 17: this.popState(); return 18;
                    break;
                case 18: this.popState(); return 18;
                    break;
                case 19: yy_.yytext=yy_.yytext.substr(1, yy_.yyleng-2).replace(/\\"/g, '"'); return 28;
                    break;
                case 20: return 30;
                    break;
                case 21: return 30;
                    break;
                case 22: return 29;
                    break;
                case 23: return 33;
                    break;
                case 24: yy_.yytext=yy_.yytext.substr(1, yy_.yyleng-2); return 33;
                    break;
                case 25: return 'INVALID';
                    break;
                case 26: return 5;
                    break;
            }
        };
        lexer.rules=[/^[^\x00]*?(?=(\{\{))/, /^[^\x00]+/, /^[^\x00]{2,}?(?=(\{\{))/, /^\{\{>/, /^\{\{#/, /^\{\{\//, /^\{\{\^/, /^\{\{\s*else\b/, /^\{\{\{/, /^\{\{&/, /^\{\{![\s\S]*?\}\}/, /^\{\{/, /^=/, /^\.(?=[} ])/, /^\.\./, /^[\/.]/, /^\s+/, /^\}\}\}/, /^\}\}/, /^"(\\["]|[^"])*"/, /^true(?=[}\s])/, /^false(?=[}\s])/, /^[0-9]+(?=[}\s])/, /^[a-zA-Z0-9_$-]+(?=[=}\s\/.])/, /^\[[^\]]*\]/, /^./, /^$/];
        lexer.conditions={ "mu": { "rules": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "INITIAL": { "rules": [0, 1, 26], "inclusive": true} }; return lexer;
    })()
    parser.lexer=lexer;
    return parser;
})();
if(typeof require!=='undefined'&&typeof exports!=='undefined') {
    exports.parser=handlebars;
    exports.parse=function () { return handlebars.parse.apply(handlebars, arguments); }
    exports.main=function commonjsMain(args) {
        if(!args[1])
            throw new Error('Usage: '+args[0]+' FILE');
        if(typeof process!=='undefined') {
            var source=require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
        } else {
            var cwd=require("file").path(require("file").cwd());
            var source=cwd.join(args[1]).read({ charset: "utf-8" });
        }
        return exports.parser.parse(source);
    }
    if(typeof module!=='undefined'&&require.main===module) {
        exports.main(typeof process!=='undefined'?process.argv.slice(1):require("system").args);
    }
};
;
// lib/handlebars/compiler/base.js
Handlebars.Parser=handlebars;

Handlebars.parse=function (string) {
    Handlebars.Parser.yy=Handlebars.AST;
    return Handlebars.Parser.parse(string);
};

Handlebars.print=function (ast) {
    return new Handlebars.PrintVisitor().accept(ast);
};

Handlebars.logger={
    DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,

    // override in the host environment
    log: function (level, str) { }
};

Handlebars.log=function (level, str) { Handlebars.logger.log(level, str); };
;
// lib/handlebars/compiler/ast.js
(function () {

    Handlebars.AST={};

    Handlebars.AST.ProgramNode=function (statements, inverse) {
        this.type="program";
        this.statements=statements;
        if(inverse) { this.inverse=new Handlebars.AST.ProgramNode(inverse); }
    };

    Handlebars.AST.MustacheNode=function (params, hash, unescaped) {
        this.type="mustache";
        this.id=params[0];
        this.params=params.slice(1);
        this.hash=hash;
        this.escaped=!unescaped;
    };

    Handlebars.AST.PartialNode=function (id, context) {
        this.type="partial";

        // TODO: disallow complex IDs

        this.id=id;
        this.context=context;
    };

    var verifyMatch=function (open, close) {
        if(open.original!==close.original) {
            throw new Handlebars.Exception(open.original+" doesn't match "+close.original);
        }
    };

    Handlebars.AST.BlockNode=function (mustache, program, close) {
        verifyMatch(mustache.id, close);
        this.type="block";
        this.mustache=mustache;
        this.program=program;
    };

    Handlebars.AST.InverseNode=function (mustache, program, close) {
        verifyMatch(mustache.id, close);
        this.type="inverse";
        this.mustache=mustache;
        this.program=program;
    };

    Handlebars.AST.ContentNode=function (string) {
        this.type="content";
        this.string=string;
    };

    Handlebars.AST.HashNode=function (pairs) {
        this.type="hash";
        this.pairs=pairs;
    };

    Handlebars.AST.IdNode=function (parts) {
        this.type="ID";
        this.original=parts.join(".");

        var dig=[], depth=0;

        for(var i=0, l=parts.length; i<l; i++) {
            var part=parts[i];

            if(part==="..") { depth++; }
            else if(part==="."||part==="this") { this.isScoped=true; }
            else { dig.push(part); }
        }

        this.parts=dig;
        this.string=dig.join('.');
        this.depth=depth;
        this.isSimple=(dig.length===1)&&(depth===0);
    };

    Handlebars.AST.StringNode=function (string) {
        this.type="STRING";
        this.string=string;
    };

    Handlebars.AST.IntegerNode=function (integer) {
        this.type="INTEGER";
        this.integer=integer;
    };

    Handlebars.AST.BooleanNode=function (bool) {
        this.type="BOOLEAN";
        this.bool=bool;
    };

    Handlebars.AST.CommentNode=function (comment) {
        this.type="comment";
        this.comment=comment;
    };

})(); ;
// lib/handlebars/utils.js
Handlebars.Exception=function (message) {
    var tmp=Error.prototype.constructor.apply(this, arguments);

    for(var p in tmp) {
        if(tmp.hasOwnProperty(p)) { this[p]=tmp[p]; }
    }

    this.message=tmp.message;
};
Handlebars.Exception.prototype=new Error;

// Build out our basic SafeString type
Handlebars.SafeString=function (string) {
    this.string=string;
};
Handlebars.SafeString.prototype.toString=function () {
    return this.string.toString();
};

(function () {
    var escape={
        "<": "&lt;",
        ">": "&gt;",
        '"': "&quot;",
        "'": "&#x27;",
        "`": "&#x60;"
    };

    var badChars=/&(?!\w+;)|[<>"'`]/g;
    var possible=/[&<>"'`]/;

    var escapeChar=function (chr) {
        return escape[chr]||"&amp;";
    };

    Handlebars.Utils={
        escapeExpression: function (string) {
            // don't escape SafeStrings, since they're already safe
            if(string instanceof Handlebars.SafeString) {
                return string.toString();
            } else if(string==null||string===false) {
                return "";
            }

            if(!possible.test(string)) { return string; }
            return string.replace(badChars, escapeChar);
        },

        isEmpty: function (value) {
            if(typeof value==="undefined") {
                return true;
            } else if(value===null) {
                return true;
            } else if(value===false) {
                return true;
            } else if(Object.prototype.toString.call(value)==="[object Array]"&&value.length===0) {
                return true;
            } else {
                return false;
            }
        }
    };
})(); ;
// lib/handlebars/compiler/compiler.js
Handlebars.Compiler=function () { };
Handlebars.JavaScriptCompiler=function () { };

(function (Compiler, JavaScriptCompiler) {
    Compiler.OPCODE_MAP={
        appendContent: 1,
        getContext: 2,
        lookupWithHelpers: 3,
        lookup: 4,
        append: 5,
        invokeMustache: 6,
        appendEscaped: 7,
        pushString: 8,
        truthyOrFallback: 9,
        functionOrFallback: 10,
        invokeProgram: 11,
        invokePartial: 12,
        push: 13,
        assignToHash: 15,
        pushStringParam: 16
    };

    Compiler.MULTI_PARAM_OPCODES={
        appendContent: 1,
        getContext: 1,
        lookupWithHelpers: 2,
        lookup: 1,
        invokeMustache: 3,
        pushString: 1,
        truthyOrFallback: 1,
        functionOrFallback: 1,
        invokeProgram: 3,
        invokePartial: 1,
        push: 1,
        assignToHash: 1,
        pushStringParam: 1
    };

    Compiler.DISASSEMBLE_MAP={};

    for(var prop in Compiler.OPCODE_MAP) {
        var value=Compiler.OPCODE_MAP[prop];
        Compiler.DISASSEMBLE_MAP[value]=prop;
    }

    Compiler.multiParamSize=function (code) {
        return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];
    };

    Compiler.prototype={
        compiler: Compiler,

        disassemble: function () {
            var opcodes=this.opcodes, opcode, nextCode;
            var out=[], str, name, value;

            for(var i=0, l=opcodes.length; i<l; i++) {
                opcode=opcodes[i];

                if(opcode==='DECLARE') {
                    name=opcodes[++i];
                    value=opcodes[++i];
                    out.push("DECLARE "+name+" = "+value);
                } else {
                    str=Compiler.DISASSEMBLE_MAP[opcode];

                    var extraParams=Compiler.multiParamSize(opcode);
                    var codes=[];

                    for(var j=0; j<extraParams; j++) {
                        nextCode=opcodes[++i];

                        if(typeof nextCode==="string") {
                            nextCode="\""+nextCode.replace("\n", "\\n")+"\"";
                        }

                        codes.push(nextCode);
                    }

                    str=str+" "+codes.join(" ");

                    out.push(str);
                }
            }

            return out.join("\n");
        },

        guid: 0,

        compile: function (program, options) {
            this.children=[];
            this.depths={ list: [] };
            this.options=options;

            // These changes will propagate to the other compiler components
            var knownHelpers=this.options.knownHelpers;
            this.options.knownHelpers={
                'helperMissing': true,
                'blockHelperMissing': true,
                'each': true,
                'if': true,
                'unless': true,
                'with': true,
                'log': true
            };
            if(knownHelpers) {
                for(var name in knownHelpers) {
                    this.options.knownHelpers[name]=knownHelpers[name];
                }
            }

            return this.program(program);
        },

        accept: function (node) {
            return this[node.type](node);
        },

        program: function (program) {
            var statements=program.statements, statement;
            this.opcodes=[];

            for(var i=0, l=statements.length; i<l; i++) {
                statement=statements[i];
                this[statement.type](statement);
            }
            this.isSimple=l===1;

            this.depths.list=this.depths.list.sort(function (a, b) {
                return a-b;
            });

            return this;
        },

        compileProgram: function (program) {
            var result=new this.compiler().compile(program, this.options);
            var guid=this.guid++;

            this.usePartial=this.usePartial||result.usePartial;

            this.children[guid]=result;

            for(var i=0, l=result.depths.list.length; i<l; i++) {
                depth=result.depths.list[i];

                if(depth<2) { continue; }
                else { this.addDepth(depth-1); }
            }

            return guid;
        },

        block: function (block) {
            var mustache=block.mustache;
            var depth, child, inverse, inverseGuid;

            var params=this.setupStackForMustache(mustache);

            var programGuid=this.compileProgram(block.program);

            if(block.program.inverse) {
                inverseGuid=this.compileProgram(block.program.inverse);
                this.declare('inverse', inverseGuid);
            }

            this.opcode('invokeProgram', programGuid, params.length, !!mustache.hash);
            this.declare('inverse', null);
            this.opcode('append');
        },

        inverse: function (block) {
            var params=this.setupStackForMustache(block.mustache);

            var programGuid=this.compileProgram(block.program);

            this.declare('inverse', programGuid);

            this.opcode('invokeProgram', null, params.length, !!block.mustache.hash);
            this.declare('inverse', null);
            this.opcode('append');
        },

        hash: function (hash) {
            var pairs=hash.pairs, pair, val;

            this.opcode('push', '{}');

            for(var i=0, l=pairs.length; i<l; i++) {
                pair=pairs[i];
                val=pair[1];

                this.accept(val);
                this.opcode('assignToHash', pair[0]);
            }
        },

        partial: function (partial) {
            var id=partial.id;
            this.usePartial=true;

            if(partial.context) {
                this.ID(partial.context);
            } else {
                this.opcode('push', 'depth0');
            }

            this.opcode('invokePartial', id.original);
            this.opcode('append');
        },

        content: function (content) {
            this.opcode('appendContent', content.string);
        },

        mustache: function (mustache) {
            var params=this.setupStackForMustache(mustache);

            this.opcode('invokeMustache', params.length, mustache.id.original, !!mustache.hash);

            if(mustache.escaped&&!this.options.noEscape) {
                this.opcode('appendEscaped');
            } else {
                this.opcode('append');
            }
        },

        ID: function (id) {
            this.addDepth(id.depth);

            this.opcode('getContext', id.depth);

            this.opcode('lookupWithHelpers', id.parts[0]||null, id.isScoped||false);

            for(var i=1, l=id.parts.length; i<l; i++) {
                this.opcode('lookup', id.parts[i]);
            }
        },

        STRING: function (string) {
            this.opcode('pushString', string.string);
        },

        INTEGER: function (integer) {
            this.opcode('push', integer.integer);
        },

        BOOLEAN: function (bool) {
            this.opcode('push', bool.bool);
        },

        comment: function () { },

        // HELPERS
        pushParams: function (params) {
            var i=params.length, param;

            while(i--) {
                param=params[i];

                if(this.options.stringParams) {
                    if(param.depth) {
                        this.addDepth(param.depth);
                    }

                    this.opcode('getContext', param.depth||0);
                    this.opcode('pushStringParam', param.string);
                } else {
                    this[param.type](param);
                }
            }
        },

        opcode: function (name, val1, val2, val3) {
            this.opcodes.push(Compiler.OPCODE_MAP[name]);
            if(val1!==undefined) { this.opcodes.push(val1); }
            if(val2!==undefined) { this.opcodes.push(val2); }
            if(val3!==undefined) { this.opcodes.push(val3); }
        },

        declare: function (name, value) {
            this.opcodes.push('DECLARE');
            this.opcodes.push(name);
            this.opcodes.push(value);
        },

        addDepth: function (depth) {
            if(depth===0) { return; }

            if(!this.depths[depth]) {
                this.depths[depth]=true;
                this.depths.list.push(depth);
            }
        },

        setupStackForMustache: function (mustache) {
            var params=mustache.params;

            this.pushParams(params);

            if(mustache.hash) {
                this.hash(mustache.hash);
            }

            this.ID(mustache.id);

            return params;
        }
    };

    JavaScriptCompiler.prototype={
        // PUBLIC API: You can override these methods in a subclass to provide
        // alternative compiled forms for name lookup and buffering semantics
        nameLookup: function (parent, name, type) {
            if(/^[0-9]+$/.test(name)) {
                return parent+"["+name+"]";
            } else if(JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
                return parent+"."+name;
            }
            else {
                return parent+"['"+name+"']";
            }
        },

        appendToBuffer: function (string) {
            if(this.environment.isSimple) {
                return "return "+string+";";
            } else {
                return "buffer += "+string+";";
            }
        },

        initializeBuffer: function () {
            return this.quotedString("");
        },

        namespace: "Handlebars",
        // END PUBLIC API

        compile: function (environment, options, context, asObject) {
            this.environment=environment;
            this.options=options||{};

            this.name=this.environment.name;
            this.isChild=!!context;
            this.context=context||{
                programs: [],
                aliases: { self: 'this' },
                registers: { list: [] }
            };

            this.preamble();

            this.stackSlot=0;
            this.stackVars=[];

            this.compileChildren(environment, options);

            var opcodes=environment.opcodes, opcode;

            this.i=0;

            for(l=opcodes.length; this.i<l; this.i++) {
                opcode=this.nextOpcode(0);

                if(opcode[0]==='DECLARE') {
                    this.i=this.i+2;
                    this[opcode[1]]=opcode[2];
                } else {
                    this.i=this.i+opcode[1].length;
                    this[opcode[0]].apply(this, opcode[1]);
                }
            }

            return this.createFunctionContext(asObject);
        },

        nextOpcode: function (n) {
            var opcodes=this.environment.opcodes, opcode=opcodes[this.i+n], name, val;
            var extraParams, codes;

            if(opcode==='DECLARE') {
                name=opcodes[this.i+1];
                val=opcodes[this.i+2];
                return ['DECLARE', name, val];
            } else {
                name=Compiler.DISASSEMBLE_MAP[opcode];

                extraParams=Compiler.multiParamSize(opcode);
                codes=[];

                for(var j=0; j<extraParams; j++) {
                    codes.push(opcodes[this.i+j+1+n]);
                }

                return [name, codes];
            }
        },

        eat: function (opcode) {
            this.i=this.i+opcode.length;
        },

        preamble: function () {
            var out=[];

            // this register will disambiguate helper lookup from finding a function in
            // a context. This is necessary for mustache compatibility, which requires
            // that context functions in blocks are evaluated by blockHelperMissing, and
            // then proceed as if the resulting value was provided to blockHelperMissing.
            this.useRegister('foundHelper');

            if(!this.isChild) {
                var namespace=this.namespace;
                var copies="helpers = helpers || "+namespace+".helpers;";
                if(this.environment.usePartial) { copies=copies+" partials = partials || "+namespace+".partials;"; }
                out.push(copies);
            } else {
                out.push('');
            }

            if(!this.environment.isSimple) {
                out.push(", buffer = "+this.initializeBuffer());
            } else {
                out.push("");
            }

            // track the last context pushed into place to allow skipping the
            // getContext opcode when it would be a noop
            this.lastContext=0;
            this.source=out;
        },

        createFunctionContext: function (asObject) {
            var locals=this.stackVars;
            if(!this.isChild) {
                locals=locals.concat(this.context.registers.list);
            }

            if(locals.length>0) {
                this.source[1]=this.source[1]+", "+locals.join(", ");
            }

            // Generate minimizer alias mappings
            if(!this.isChild) {
                var aliases=[]
                for(var alias in this.context.aliases) {
                    this.source[1]=this.source[1]+', '+alias+'='+this.context.aliases[alias];
                }
            }

            if(this.source[1]) {
                this.source[1]="var "+this.source[1].substring(2)+";";
            }

            // Merge children
            if(!this.isChild) {
                this.source[1]+='\n'+this.context.programs.join('\n')+'\n';
            }

            if(!this.environment.isSimple) {
                this.source.push("return buffer;");
            }

            var params=this.isChild?["depth0", "data"]:["Handlebars", "depth0", "helpers", "partials", "data"];

            for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
                params.push("depth"+this.environment.depths.list[i]);
            }

            if(asObject) {
                params.push(this.source.join("\n  "));

                return Function.apply(this, params);
            } else {
                var functionSource='function '+(this.name||'')+'('+params.join(',')+') {\n  '+this.source.join("\n  ")+'}';
                Handlebars.log(Handlebars.logger.DEBUG, functionSource+"\n\n");
                return functionSource;
            }
        },

        appendContent: function (content) {
            this.source.push(this.appendToBuffer(this.quotedString(content)));
        },

        append: function () {
            var local=this.popStack();
            this.source.push("if("+local+" || "+local+" === 0) { "+this.appendToBuffer(local)+" }");
            if(this.environment.isSimple) {
                this.source.push("else { "+this.appendToBuffer("''")+" }");
            }
        },

        appendEscaped: function () {
            var opcode=this.nextOpcode(1), extra="";
            this.context.aliases.escapeExpression='this.escapeExpression';

            if(opcode[0]==='appendContent') {
                extra=" + "+this.quotedString(opcode[1][0]);
                this.eat(opcode);
            }

            this.source.push(this.appendToBuffer("escapeExpression("+this.popStack()+")"+extra));
        },

        getContext: function (depth) {
            if(this.lastContext!==depth) {
                this.lastContext=depth;
            }
        },

        lookupWithHelpers: function (name, isScoped) {
            if(name) {
                var topStack=this.nextStack();

                this.usingKnownHelper=false;

                var toPush;
                if(!isScoped&&this.options.knownHelpers[name]) {
                    toPush=topStack+" = "+this.nameLookup('helpers', name, 'helper');
                    this.usingKnownHelper=true;
                } else if(isScoped||this.options.knownHelpersOnly) {
                    toPush=topStack+" = "+this.nameLookup('depth'+this.lastContext, name, 'context');
                } else {
                    this.register('foundHelper', this.nameLookup('helpers', name, 'helper'));
                    toPush=topStack+" = foundHelper || "+this.nameLookup('depth'+this.lastContext, name, 'context');
                }

                toPush+=';';
                this.source.push(toPush);
            } else {
                this.pushStack('depth'+this.lastContext);
            }
        },

        lookup: function (name) {
            var topStack=this.topStack();
            this.source.push(topStack+" = ("+topStack+" === null || "+topStack+" === undefined || "+topStack+" === false ? "+
 				topStack+" : "+this.nameLookup(topStack, name, 'context')+");");
        },

        pushStringParam: function (string) {
            this.pushStack('depth'+this.lastContext);
            this.pushString(string);
        },

        pushString: function (string) {
            this.pushStack(this.quotedString(string));
        },

        push: function (name) {
            this.pushStack(name);
        },

        invokeMustache: function (paramSize, original, hasHash) {
            this.populateParams(paramSize, this.quotedString(original), "{}", null, hasHash, function (nextStack, helperMissingString, id) {
                if(!this.usingKnownHelper) {
                    this.context.aliases.helperMissing='helpers.helperMissing';
                    this.context.aliases.undef='void 0';
                    this.source.push("else if("+id+"=== undef) { "+nextStack+" = helperMissing.call("+helperMissingString+"); }");
                    if(nextStack!==id) {
                        this.source.push("else { "+nextStack+" = "+id+"; }");
                    }
                }
            });
        },

        invokeProgram: function (guid, paramSize, hasHash) {
            var inverse=this.programExpression(this.inverse);
            var mainProgram=this.programExpression(guid);

            this.populateParams(paramSize, null, mainProgram, inverse, hasHash, function (nextStack, helperMissingString, id) {
                if(!this.usingKnownHelper) {
                    this.context.aliases.blockHelperMissing='helpers.blockHelperMissing';
                    this.source.push("else { "+nextStack+" = blockHelperMissing.call("+helperMissingString+"); }");
                }
            });
        },

        populateParams: function (paramSize, helperId, program, inverse, hasHash, fn) {
            var needsRegister=hasHash||this.options.stringParams||inverse||this.options.data;
            var id=this.popStack(), nextStack;
            var params=[], param, stringParam, stringOptions;

            if(needsRegister) {
                this.register('tmp1', program);
                stringOptions='tmp1';
            } else {
                stringOptions='{ hash: {} }';
            }

            if(needsRegister) {
                var hash=(hasHash?this.popStack():'{}');
                this.source.push('tmp1.hash = '+hash+';');
            }

            if(this.options.stringParams) {
                this.source.push('tmp1.contexts = [];');
            }

            for(var i=0; i<paramSize; i++) {
                param=this.popStack();
                params.push(param);

                if(this.options.stringParams) {
                    this.source.push('tmp1.contexts.push('+this.popStack()+');');
                }
            }

            if(inverse) {
                this.source.push('tmp1.fn = tmp1;');
                this.source.push('tmp1.inverse = '+inverse+';');
            }

            if(this.options.data) {
                this.source.push('tmp1.data = data;');
            }

            params.push(stringOptions);

            this.populateCall(params, id, helperId||id, fn, program!=='{}');
        },

        populateCall: function (params, id, helperId, fn, program) {
            var paramString=["depth0"].concat(params).join(", ");
            var helperMissingString=["depth0"].concat(helperId).concat(params).join(", ");

            var nextStack=this.nextStack();

            if(this.usingKnownHelper) {
                this.source.push(nextStack+" = "+id+".call("+paramString+");");
            } else {
                this.context.aliases.functionType='"function"';
                var condition=program?"foundHelper && ":""
                this.source.push("if("+condition+"typeof "+id+" === functionType) { "+nextStack+" = "+id+".call("+paramString+"); }");
            }
            fn.call(this, nextStack, helperMissingString, id);
            this.usingKnownHelper=false;
        },

        invokePartial: function (context) {
            params=[this.nameLookup('partials', context, 'partial'), "'"+context+"'", this.popStack(), "helpers", "partials"];

            if(this.options.data) {
                params.push("data");
            }

            this.pushStack("self.invokePartial("+params.join(", ")+");");
        },

        assignToHash: function (key) {
            var value=this.popStack();
            var hash=this.topStack();

            this.source.push(hash+"['"+key+"'] = "+value+";");
        },

        // HELPERS

        compiler: JavaScriptCompiler,

        compileChildren: function (environment, options) {
            var children=environment.children, child, compiler;

            for(var i=0, l=children.length; i<l; i++) {
                child=children[i];
                compiler=new this.compiler();

                this.context.programs.push('');     // Placeholder to prevent name conflicts for nested children
                var index=this.context.programs.length;
                child.index=index;
                child.name='program'+index;
                this.context.programs[index]=compiler.compile(child, options, this.context);
            }
        },

        programExpression: function (guid) {
            if(guid==null) { return "self.noop"; }

            var child=this.environment.children[guid],
          depths=child.depths.list;
            var programParams=[child.index, child.name, "data"];

            for(var i=0, l=depths.length; i<l; i++) {
                depth=depths[i];

                if(depth===1) { programParams.push("depth0"); }
                else { programParams.push("depth"+(depth-1)); }
            }

            if(depths.length===0) {
                return "self.program("+programParams.join(", ")+")";
            } else {
                programParams.shift();
                return "self.programWithDepth("+programParams.join(", ")+")";
            }
        },

        register: function (name, val) {
            this.useRegister(name);
            this.source.push(name+" = "+val+";");
        },

        useRegister: function (name) {
            if(!this.context.registers[name]) {
                this.context.registers[name]=true;
                this.context.registers.list.push(name);
            }
        },

        pushStack: function (item) {
            this.source.push(this.nextStack()+" = "+item+";");
            return "stack"+this.stackSlot;
        },

        nextStack: function () {
            this.stackSlot++;
            if(this.stackSlot>this.stackVars.length) { this.stackVars.push("stack"+this.stackSlot); }
            return "stack"+this.stackSlot;
        },

        popStack: function () {
            return "stack"+this.stackSlot--;
        },

        topStack: function () {
            return "stack"+this.stackSlot;
        },

        quotedString: function (str) {
            return '"'+str
        .replace(/\\/g, '\\\\')
        .replace(/"/g, '\\"')
        .replace(/\n/g, '\\n')
        .replace(/\r/g, '\\r')+'"';
        }
    };

    var reservedWords=(
    "break else new var"+
    " case finally return void"+
    " catch for switch while"+
    " continue function this with"+
    " default if throw"+
    " delete in try"+
    " do instanceof typeof"+
    " abstract enum int short"+
    " boolean export interface static"+
    " byte extends long super"+
    " char final native synchronized"+
    " class float package throws"+
    " const goto private transient"+
    " debugger implements protected volatile"+
    " double import public let yield"
  ).split(" ");

    var compilerWords=JavaScriptCompiler.RESERVED_WORDS={};

    for(var i=0, l=reservedWords.length; i<l; i++) {
        compilerWords[reservedWords[i]]=true;
    }

    JavaScriptCompiler.isValidJavaScriptVariableName=function (name) {
        if(!JavaScriptCompiler.RESERVED_WORDS[name]&&/^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
            return true;
        }
        return false;
    }

})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);

Handlebars.precompile=function (string, options) {
    options=options||{};

    var ast=Handlebars.parse(string);
    var environment=new Handlebars.Compiler().compile(ast, options);
    return new Handlebars.JavaScriptCompiler().compile(environment, options);
};

Handlebars.compile=function (string, options) {
    options=options||{};

    var compiled;
    function compile() {
        var ast=Handlebars.parse(string);
        var environment=new Handlebars.Compiler().compile(ast, options);
        var templateSpec=new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
        return Handlebars.template(templateSpec);
    }

    // Template is only compiled on first use and cached after that point.
    return function (context, options) {
        if(!compiled) {
            compiled=compile();
        }
        return compiled.call(this, context, options);
    };
};
;
// lib/handlebars/runtime.js
Handlebars.VM={
    template: function (templateSpec) {
        // Just add water
        var container={
            escapeExpression: Handlebars.Utils.escapeExpression,
            invokePartial: Handlebars.VM.invokePartial,
            programs: [],
            program: function (i, fn, data) {
                var programWrapper=this.programs[i];
                if(data) {
                    return Handlebars.VM.program(fn, data);
                } else if(programWrapper) {
                    return programWrapper;
                } else {
                    programWrapper=this.programs[i]=Handlebars.VM.program(fn);
                    return programWrapper;
                }
            },
            programWithDepth: Handlebars.VM.programWithDepth,
            noop: Handlebars.VM.noop
        };

        return function (context, options) {
            options=options||{};
            return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
        };
    },

    programWithDepth: function (fn, data, $depth) {
        var args=Array.prototype.slice.call(arguments, 2);

        return function (context, options) {
            options=options||{};

            return fn.apply(this, [context, options.data||data].concat(args));
        };
    },
    program: function (fn, data) {
        return function (context, options) {
            options=options||{};

            return fn(context, options.data||data);
        };
    },
    noop: function () { return ""; },
    invokePartial: function (partial, name, context, helpers, partials, data) {
        options={ helpers: helpers, partials: partials, data: data };

        if(partial===undefined) {
            throw new Handlebars.Exception("The partial "+name+" could not be found");
        } else if(partial instanceof Function) {
            return partial(context, options);
        } else if(!Handlebars.compile) {
            throw new Handlebars.Exception("The partial "+name+" could not be compiled when running in runtime-only mode");
        } else {
            partials[name]=Handlebars.compile(partial);
            return partials[name](context, options);
        }
    }
};

Handlebars.template=Handlebars.VM.template;
;
